﻿using EnterpriseDT.Net.Ftp;
using FTPC.Config;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FTPC {
    public partial class MainForm : Form {

        //FTPConnection ftpConnection;
        UpLoadFileTools uploadFileTools;

        ArrayList putJobList;

        object lockPutJobList = new object ( );

        ConfigMgr conf;

        int lastPut = 0;

        bool isBiggerThanMaxInt = false;

        public MainForm() {
            this.conf = ConfigMgr.Instance;
            InitializeComponent ( );
            this.txtUername.Text = this.conf.Application.username;
            this.txtPwd.Text = this.conf.Application.pwd;
            this.txtServerIP.Text = this.conf.Application.ip;
            this.txtServerPort.Text = this.conf.Application.port;
            start ( );
        }

        public void addPutJobList(UpLoadJob job) {
            if (putJobList == null) putJobList = new ArrayList ( );
            lock (lockPutJobList) {
                putJobList.Add (job);
            }
        }

        public void removeAllJob() {
            lock (lockPutJobList) {
                this.putJobList.RemoveRange (0, this.putJobList.Count);
                this.lastPut = 0;
            }
        }

        public ArrayList getPutJobList() {
            return putJobList;
        }

        public async Task<string> doPut() {
            ArrayList listJob;
            try {
                while (true) {
                    listJob = getPutJobList ( );
                    if (listJob != null) {
                        for (int i = lastPut; i < listJob.Count; i++) {
                            UpLoadJob job = (UpLoadJob)listJob[i];
                            try {
                                job.setState (JobState.MD5);
                                FileInfo fileinfo = new FileInfo (job.localpath);
                                initProgressBar (job);
                                setlabPutNow (job.filename);
                                addLog ("开始上传" + job.filename);
                                if (uploadFileTools.MyUpload (job))
                                    lastPut++;
                            } catch (Exception ex) {
                                job.setState (JobState.ERROR);
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                addLog ("出现异常" + ex.Message + "\r\n");
            }
            return "Finish";
        }

        /// <summary>
        /// 初始化进度条
        /// </summary>
        /// <param name="job"></param>
        private void initProgressBar(UpLoadJob job) {
            int progressBarValue = 0;
            if (isBiggerThanInt (job.filesize)) {
                isBiggerThanMaxInt = true;
                progressBarValue = (int)(job.filesize / 1024);
            } else {
                isBiggerThanMaxInt = false;
                progressBarValue = (int)job.filesize;
            }
            this.setProgressBar1Max (progressBarValue);
            this.setProgressBar1Value (0);
        }

        

        public bool initUploadFileTools() {
            try {
                if (this.uploadFileTools == null) {
                    if (this.txtServerIP.Text == "") {
                        MessageBox.Show ( "请输入服务器地址！", "警告");
                        return false;
                    }
                    if (this.txtServerPort.Text == "") {
                        MessageBox.Show ("请输入端口号！", "警告");
                        return false;
                    }
                    if (this.txtUername.Text != "" && this.txtPwd.Text != "") {
                        uploadFileTools = new UpLoadFileTools (this.txtServerIP.Text, this.txtServerPort.Text,
                                                              this.txtUername.Text,
                                                              this.txtPwd.Text);
                        uploadFileTools.BytesTransferred += uploadFile_BytesTransferred;
                        uploadFileTools.TransferComplete += uploadFile_TransferComplete;
                        if (this.txtServerIP.Text != conf.Application.ip) {
                            conf.Application.ip = txtServerIP.Text;
                            conf._cfg.Save (ConfigurationSaveMode.Modified);
                        }
                        if (this.txtServerPort.Text != conf.Application.port) {
                            conf.Application.port = txtServerPort.Text;
                            conf._cfg.Save (ConfigurationSaveMode.Modified);
                        }
                        if (this.txtUername.Text != conf.Application.username) {
                            conf.Application.username = txtUername.Text;
                            conf._cfg.Save (ConfigurationSaveMode.Modified);
                        }
                        if (this.txtPwd.Text != conf.Application.pwd) {
                            conf.Application.pwd = txtPwd.Text;
                            conf._cfg.Save (ConfigurationSaveMode.Modified);
                        }
                        this.txtServerIP.Enabled = false;
                        this.txtServerPort.Enabled = false;
                        this.txtUername.Enabled = false;
                        this.txtPwd.Enabled = false;
                        this.uploadFileTools.cleanFileinfo (null);
                        return true;
                    } else {
                        MessageBox.Show ("请输入用户名密码", "F1-initUploadFileTools1");
                        return false;
                    }
                }
                return true;
            } catch (Exception ex) {
                MessageBox.Show ("程序异常，请重新启动", "F1-initUploadFileTools2");
                return false;
            }
        }

        public void closeUploadFileTools() {
            this.uploadFileTools = null;
            this.txtUername.Enabled = true;
            this.txtPwd.Enabled = true;
        }

        public async void start() {
            string result = await Task.Run (() => doPut ( ));
        }

        void uploadFile_TransferComplete(object sender, TransferEventArgs e) {
            if (e.RemoteFilename.IndexOf (".fileinfo") > 0) return;
            UpLoadJob uploadjob = (UpLoadJob)this.putJobList[lastPut];
            if (uploadFileTools.getExistsRemoteFileSize (e.RemoteFilename) == uploadjob.filesize) {
                this.addLog ("传输完成 " + e.RemoteFilename);
                uploadjob.setState (JobState.UPLOADED);
            } else {
                this.addLog ("数据丢失，请重新上传 " + e.RemoteFilename);
                uploadjob.setState (JobState.ERROR);
            }
            this.setProgressBar1Value (0);
            this.uploadFileTools.cleanFileinfo (e.RemoteFilename);
        }

        private void addLog(string log) {
            log = DateTime.Now.ToLocalTime ( ).ToString ( ) + log;
            this.setlog (log);
        }

        private void btnTest_Click(object sender, EventArgs e) {
            try {
                if (!initUploadFileTools ( )) return;
                UpLoadJob upLoadJob = null;
                using (OpenFileDialog file = new OpenFileDialog ( )) {
                    file.Multiselect = true;
                    //限制选择的文件格式
                    //file.Filter = "打包文件|*.zip;*.pdf;*.charts;*.dat";
                    if (file.ShowDialog ( ) == DialogResult.OK) {
                        int i = 0;
                        foreach (string filename in file.FileNames) {
                            long filesize = new FileInfo (filename).Length;
                            upLoadJob = new UpLoadJob (filename, file.SafeFileNames[i], filesize);
                            upLoadJob.stateChange += upLoadJob_stateChange;
                            i++;

                            addLog ("等待上传：" + labNowPut.Text);
                            this.Refresh ( );
                            if (upLoadJob != null) {
                                addPutJobList (upLoadJob);
                                upLoadJob.setState (JobState.CREATE);
                            } else addLog ("添加文件出错");
                        }
                    } else {
                        txtServerIP.Enabled = true;
                        txtServerPort.Enabled = true;
                        txtUername.Enabled = true;
                        txtPwd.Enabled = true;
                    }
                }
                this.Refresh ( );
            } catch (Exception ex) {
                addLog (ex.Message);
            }
        }

        void upLoadJob_stateChange(object sender, EventArgs e) {
            this.flushlboxPutJob ( );
        }

        void uploadFile_BytesTransferred(object sender, BytesTransferredEventArgs e) {
            if (e.RemoteFile.IndexOf (".fileinfo") > 0) return;

            long resourceValue = e.ByteCount + e.ResumeOffset;
            int progressBarValue = 0;
            if (isBiggerThanMaxInt) {
                progressBarValue = (int)(resourceValue / 1024);
            } else {
                progressBarValue = (int)resourceValue;
            }
            this.setProgressBar1Value (progressBarValue);
        }

        private void btnStop_Click(object sender, EventArgs e) {
            if (this.uploadFileTools == null) return;
            this.uploadFileTools.disConnect ( );
            this.progressBar1.Value = 0;
            this.labNowPut.Text = "传输中止！";
            this.addLog ("传输中止！后续任务已经清除。");
            this.removeAllJob ( );
            flushlboxPutJob ( );
            //closeUploadFileTools();
        }

        public void setProgressBar1Value(int value) {
            Invoke (new Action (() => { this.progressBar1.Value = value; }));
        }

        public void setProgressBar1Max(int max) {
            Invoke (new Action (() => { this.progressBar1.Maximum = max; }));
        }

        public void setlabPutNow(string putJobName) {
            Invoke (new Action (() => { this.labNowPut.Text = putJobName; }));
        }

        public void setlog(string log) {
            Invoke (new Action (() => {
                this.txtLog.AppendText (log + "\r\n");
                this.txtLog.ScrollToCaret ( );
            }));
        }

        public void flushlboxPutJob() {
            Invoke (new Action (() => {
                this.lboxJob.DataSource = null;
                this.lboxJob.DataSource = this.putJobList;
                this.Refresh ( );
            }));
        }

        private void labNowPut_Click(object sender, EventArgs e) {

        }


        /// <summary>
        /// 验证resourceValue是否超越int类型的范围
        /// 越界，返回true，否则返回false
        /// </summary>
        /// <param name="resourceValue"></param>
        /// <returns></returns>
        public bool isBiggerThanInt(long resourceValue) {
            int intValue = (int)resourceValue;
            long newValue = (long)intValue;
            return resourceValue != newValue;
        }
    }
}
